#include<cstdlib>

#include "KeyManager.h"

#include <iostream>
#include <cstdlib>

#include "Camera.h"
#include "Scene.h"

const double PI = 3.14159265;

KeyManager::KeyManager(Game* _game)
   : mouseButton(0), active(0), xMouseOrigin(0), yMouseOrigin(0)
{
   game = _game;
}

void KeyManager::setButtonState(int _button, int _state, int x, int y)
{
   if (_state == 1) // button released
   {
      if (active == 200) // stick
      {
         game->getScene()->getStick()->release();
      } 
      else if (active >= 100 && active < 200) // a IDrawable object
      {   
         IDrawable::getIDrawable(active - 100)->setActive();
      }
      
      active = 0;      
      return;
   }
      
   mouseButton = _button;
   xMouseOrigin = x;
   yMouseOrigin = y;   
   angleOrigin = game->getScene()->getAngle();
   
   // set active state   
 	static GLuint buff[64] = {0};
 	GLint hits, view[4];
 	int id;
   
 	glSelectBuffer(64, buff); // Setup selection buffer
 	glGetIntegerv(GL_VIEWPORT, view); // Get the viewport
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glRenderMode(GL_SELECT);
	glLoadIdentity();
	gluPickMatrix(x, view[3] - y + view[1], 2, 2, view);	
	game->getCamera()->setPerspective(game->isTopView());
	game->draw();
	hits = glRenderMode(GL_RENDER);
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
 	for (int i = 0; i < hits; i++)
   {
      int object = (GLubyte)buff[i * 4 + 3];
      if (object > active)
         active = object;
   }

   if (active >= 100 && active < 200)
      IDrawable::getIDrawable(active - 100)->setActive();
   
 	glMatrixMode(GL_MODELVIEW);
}

void KeyManager::setMousePosition(int x, int y)
{
   if (mouseButton == 0) // left click
   {
      if (active == 1 && game->isTopView() != true) // table
      {
         double angleChange = getAngle(x, y) - getAngle(xMouseOrigin, yMouseOrigin);
         
         double newAngle = angleOrigin - angleChange;
         
         if (newAngle < 0)
            newAngle += 360;
         
         game->getScene()->setAngle(newAngle);         
      }
      else if (active == 200 && game->isTopView() != true) // stick
      {
         
         double d = y - yMouseOrigin;
         
         if (d > 0)
         {
            double percent = d / (game->getHeight() / 2.0);
            if (percent > 1)
               percent = 1;
            game->getScene()->getStick()->setPullBackPercent(percent);
         } else {
            game->getScene()->getStick()->setPullBackPercent(0);
         }
            
      }
   }
}

double KeyManager::getAngle(int x, int y)
{
   double rX = x - ((double) game->getWidth() / 2.0);
   double rY = ((double) game->getHeight() / 2.0) - y;
   
   double angle = 0;
   if (rX != 0)
   {
      angle = atan(rY/rX) * 180 / PI;
      
      if (rX < 0) // Add PI to 2nd and 3rd quadrant
         angle += 180;
      else if (rY < 0) // add 2 PI to last quadrant
         angle += 360;        
   }
   else if (rY > 0)
      return 90;
   else
      return 270;

   return angle;
}


void KeyManager::keyChange(unsigned char key, int x, int y)
{
   switch (key)
   {
      case 27: // ESC key exits
         exit (0);
         break;
      case 'x':
         game->setTopView(!game->isTopView());
         break;
   }  
}

void KeyManager::specialKeyChange(int key, int x, int y)
{
   switch (key)
   {
      case GLUT_KEY_LEFT:
         game->getScene()->getStick()->moveXOffset(-0.1);
         break;         
      case GLUT_KEY_RIGHT:
         game->getScene()->getStick()->moveXOffset(0.1);
         break;
      case GLUT_KEY_UP:
         game->getScene()->getStick()->moveYOffset(0.1);
         break;
      case GLUT_KEY_DOWN:
         game->getScene()->getStick()->moveYOffset(-0.1);
         break;
   }  
}


